﻿using System;
using System.Collections.Generic;
using UnityEngine;

[Serializable]
public class PoolConfig {
    /// <summary>
    /// 生成对象的数量
    /// </summary>
    public int poolCount;
    /// <summary>
    /// 需要创建对象的预制
    /// </summary>
    public GameObject prefab;
    /// <summary>
    /// 创建的对象池的名字
    /// </summary>
    public string poolName;
}
public class ObjectPool : MonoBehaviour {
    private static ObjectPool _instance;
    public static ObjectPool Ins {
        get { return _instance; }
    }
    private Dictionary<string, List<GameObject>> poolObjectDict = new Dictionary<string, List<GameObject>> ();
    private Dictionary<string, GameObject> spawnObjectDict = new Dictionary<string, GameObject> ();
    void Awake () {
        _instance = this;
    }
    /// <summary>
    /// 根据PoolConfig的配置文件创建对象池
    /// </summary>
    /// <param name="poolConfig"></param>
    public void CreatePool (PoolConfig poolConfig,Action createPoolAction=null) {
        if (poolConfig.prefab != null && poolConfig.poolName != string.Empty && !Ins.poolObjectDict.ContainsKey (poolConfig.poolName)) {
            var lists = new List<GameObject> ();
            Ins.poolObjectDict.Add (poolConfig.poolName, lists);
            if (poolConfig.poolCount > 0) {
                bool active = poolConfig.prefab.activeSelf;
                var index = 0;
                //Transform parent = Instance.transform;
                while (lists.Count < poolConfig.poolCount) {
                    var obj = GameObject.Instantiate (poolConfig.prefab);
                    obj.name = poolConfig.poolName + (index++).ToString ();
                    obj.transform.parent = this.transform;
                    lists.Add (obj);
                    //lists.AddAfter(obj,);
                    obj.SetActive (false);
                }
            }
            if (createPoolAction!=null)createPoolAction();
        } else {
            Debug.LogWarning ("已经存在相同名称的对象池");
        }
    }
    /// <summary>
    /// 从池子中取出一个对象使用
    /// </summary>
    /// <param name="name">对象池的名字</param>
    /// <returns></returns>
    public GameObject Spawn (PoolConfig poolConfig, Action spawnAction=null) {
        List<GameObject> list;
        GameObject obj = null;
        if (Ins.poolObjectDict.TryGetValue (poolConfig.poolName, out list)) {
            obj = null;
            if (list.Count > 0) {
                while (obj == null && list.Count > 0) {
                    obj = list[0];
                    list.RemoveAt (0);
                }
                if (obj != null) {
                    obj.SetActive (true);                    
                    // Instance.spawnedObjects.Add(obj, prefab);
                    Ins.spawnObjectDict.Add (obj.name, obj);
                    if (spawnAction != null) spawnAction ();
                    return obj;
                }
            }
            obj=GameObject.Instantiate(poolConfig.prefab);    
            obj.gameObject.name= poolConfig.poolName +(poolConfig.poolCount).ToString();
            poolConfig.poolCount++;
            Ins.poolObjectDict[poolConfig.poolName].Add(obj);
            obj.transform.parent = this.transform;
            Debug.Log("集合中超出预设数量，自动扩充");
            return obj;
        }else{
            Debug.Log("池子中不包含你想要查找的对象");
            obj=GameObject.Instantiate(poolConfig.prefab);
            obj.gameObject.name= poolConfig.poolName +(poolConfig.poolCount).ToString();
            poolConfig.poolCount++;
            Ins.poolObjectDict[poolConfig.poolName].Add(obj);
            obj.transform.parent = this.transform;
            return obj;
        }     
    }
    /// <summary>
    /// 回收池子中的对象
    /// </summary>
    /// <param name="poolName">对象池的名字</param>
    /// <param name="objectName">回收对象的名字</param>
    /// <param name="RecyleAction">回收完成回掉函数</param>
    public static void Recyle (string poolName, string objectName, Action RecyleAction = null) {
        GameObject obj;
        if (Ins.spawnObjectDict.TryGetValue (objectName, out obj)) {
            Ins.poolObjectDict[poolName].Add (obj);
            Ins.spawnObjectDict.Remove (objectName);
            obj.transform.parent = Ins.transform;
            obj.gameObject.SetActive (false);
            if (RecyleAction != null) {
                RecyleAction ();
            }
        }
    }
}